package gatperdut.chato.core.cdo;

import gatperdut.chato.model.Chato.Chato;
import gatperdut.chato.model.Chato.ChatoPackage;
import gatperdut.chato.model.Chato.Constant.ConstantPackage;
import gatperdut.chato.model.Chato.Container.ContainerPackage;
import gatperdut.chato.model.Chato.Craft.CraftPackage;
import gatperdut.chato.model.Chato.Entity.EntityPackage;
import gatperdut.chato.model.Chato.Item.ItemPackage;
import gatperdut.chato.model.Chato.Player.PlayerPackage;
import gatperdut.chato.model.Chato.Room.RoomPackage;
import gatperdut.chato.model.Chato.Util.UtilPackage;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import org.apache.log4j.Logger;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.internal.common.id.CDOIDObjectLongImpl;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.session.CDOSessionConfiguration;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;

public class CDODatasource {

    private Logger logger = Logger.getLogger( CDODatasource.class );

    private CDOSessionConfiguration sessionConfiguration;

    private CDOSession session = null;

    private CDOTransaction transaction;

    private CDOResource cdoResource;

    public void init() {

        logger.info( "Initializing CDO datasource." );

        if ( session == null ) {
            session = sessionConfiguration.openSession();
            ChatoPackage.eINSTANCE.eClass();
            ContainerPackage.eINSTANCE.eClass();
            transaction = session.openTransaction();
            cdoResource = transaction.getOrCreateResource( "/myResource" );

            ChatoPackage.eINSTANCE.getClass();
            ConstantPackage.eINSTANCE.getClass();
            ContainerPackage.eINSTANCE.getClass();
            CraftPackage.eINSTANCE.getClass();
            EntityPackage.eINSTANCE.getClass();
            ItemPackage.eINSTANCE.getClass();
            PlayerPackage.eINSTANCE.getClass();
            RoomPackage.eINSTANCE.getClass();
            UtilPackage.eINSTANCE.getClass();

            checkResourceContents();
        }
    }

    public void save() {

        getLogger().info( "CDO datasource: save." );

        if ( getTransaction() == null ) {
            throw new IllegalStateException();
        }

        try {
            getTransaction().commit();
        }
        catch ( CommitException e ) {
            e.printStackTrace();
        }
    }

    private void checkResourceContents() {
        if ( getCdoResource().getContents().isEmpty() ) {
            logger.info( "CDO datasource empty: loading clean model." );

            URL url;

            try {
                url = new URL( "file:modelinstance/chato.xmi" );
                InputStream inputStream = url.openConnection().getInputStream();
                XMIResource xmiResource = new XMIResourceImpl();
                xmiResource.load( inputStream, new HashMap<Object, Object>() );
                Chato chato = (Chato) xmiResource.getContents().get( 0 );
                getCdoResource().getContents().add( chato );
                inputStream.close();
            }
            catch ( MalformedURLException murle ) {
                murle.printStackTrace();
            }
            catch ( IOException ioe ) {
                ioe.printStackTrace();
            }
            save();
        }
    }

    public Chato getChato() {
        if ( getCdoResource() == null ) {
            throw new IllegalArgumentException();
        }

        return (Chato) getCdoResource().getContents().get( 0 );
    }

    public void shutdown() {
        getSession().close();
    }

    public EObject fetchByCDOURIFragment( String cdoIDURIFragment ) {
        CDOID cdoID = CDOIDObjectLongImpl.create( cdoIDURIFragment );
        getTransaction().getObject( cdoID );
        return null;
    }

    public Logger getLogger() {
        return logger;
    }

    public void setLogger( Logger logger ) {
        this.logger = logger;
    }

    public CDOSessionConfiguration getSessionConfiguration() {
        return sessionConfiguration;
    }

    public void setSessionConfiguration( CDOSessionConfiguration sessionConfiguration ) {
        this.sessionConfiguration = sessionConfiguration;
    }

    public CDOSession getSession() {
        return session;
    }

    public void setSession( CDOSession session ) {
        this.session = session;
    }

    public CDOTransaction getTransaction() {
        return transaction;
    }

    public void setTransaction( CDOTransaction transaction ) {
        this.transaction = transaction;
    }

    public CDOResource getCdoResource() {
        return cdoResource;
    }

    public void setCdoResource( CDOResource cdoResource ) {
        this.cdoResource = cdoResource;
    }
}
